
`ifdef isALTERA
`define PC_RECORD 1
`define DEBUG_STASH 1
`define SHIFT_IP 1
`endif

//edited 
module mycpu (
    input          clk,
    input          reset_n,
    //数据
    output reg [31:0] avm_m0_address       ,     //    m0.address
    output            avm_m0_read          ,        //      .read
    output            avm_m0_write         ,       //      .write
    input      [31:0] avm_m0_readdata      ,    //      .readdata
    output     [31:0] avm_m0_writedata     ,   //      .writedata
    output      [3:0] avm_m0_byteenable    ,    //      .readdata
    input             avm_m0_waitrequest   , //      .waitrequest
    input             irq_req,
    input       [4:0] irq_id,
    
    output     [31:0] avm_m1_address       ,     //    m0.address
    output            avm_m1_read          ,        //      .read
    input      [31:0] avm_m1_readdata      ,    //      .readdata
    input             avm_m1_waitrequest   , //      .waitrequest

    input             debug_reset_n,
    input             halt_debug,
    input             force_halt,
    input             debug_step,
    output reg        halt_cpu,
    output reg [31:0] curr_data,
    output reg [31:0] pcResult,
    output reg [31:0] private_offset,
    output reg [31:0] private_offset_rear,
    output reg [31:0] pc,
    output reg [31:0] cpu_address,
    output reg        irq_enable,
    output reg [27:0] performance_ins_count,
    output reg [29:0] performance_clk_count,
    input             performance_count_on ,
    input             performance_count_rst,

    input             debug_rw,
    input       [2:0] debug_rw_cmd,
    input             debug_read_ins,
    input      [31:0] debug_address,
    input      [31:0] debug_writedata,

    input       [5:0] debug_regAddr,
    output     [31:0] debug_regData,

    input       [7:0] pc_record_index_read,
    output     [31:0] pc_record_data,
    output  reg [7:0] pc_record_index,
    
    input       [7:0] debug_stash_index_read,
    output     [31:0] debug_stash_data,
    output  reg [7:0] debug_stash_index
  );

  //wire [31:0] probe = debug_writedata;
  //wire [31:0] prob_out;
  //	altsource_probe	altsource_probe_component (
  //				.probe (probe),
  //				.source (prob_out)
  //				);
  //	defparam
  //		altsource_probe_component.enable_metastability = "NO",
  //		altsource_probe_component.instance_id = "NONE",
  //		altsource_probe_component.probe_width = 32,
  //		altsource_probe_component.sld_auto_instance_index = "YES",
  //		altsource_probe_component.sld_instance_index = 1,
  //		altsource_probe_component.source_initial_value = " 0",
  //		altsource_probe_component.source_width = 32;


  //大家好，这次更新了图形界面，硬件设计也做了很多优化
  //这是FPGA开发板，板载32M sdram，我扩展了一片，总共64M字节
  //这是IO扩展板，扩展了hdmi输出，键盘鼠标输入，ROM芯片，时钟芯片，sd卡座
  //cpu 最高频率能跑到75Mhz，平均每3个周期能执行1条指令
  //整体性能大约是80386 到 80486 的水平
  //启动
  //第一个应用是文件列表，文本浏览，和jpg图片解码
  //第二个应用是扫雷
  //第三个应用是俄罗斯方块
  //第四个应用是分形图，测试浮点性能
  
  
  //我非常想在fpga上运行命令与征服一代DOS版
  //两个方案：一是完全复刻兼容486的PC机，这个难度非常大，486指令集相当复杂，外设，显示等等的资料也很难找
  //二是移植源码，不知道有谁知道哪里有C&C的源码？
  
  
  //32:ins
  //n:预测字 0：无预测，PC+4 否则-n
  
  //流水线每一级的信号：停止信号，气泡（not valid）
  
  //1，取指令+解码         解码将指令字转成各个alu的EA???
  //hlt状态下，存储器等待，时产生气泡
  //hlt指令：置hlt状态1，并flush流水线
  //参考PC 和 预测字段，获取指令
  
  //以下每级流水线有PCchange标志，和寄存器change标志，取指令级发现PC冲突和寄存器冲突，则产生气泡
  //{pc冲突时，停止取指令} 条件：流水线里有PC指令
  //{总线冲突时，停止取指令}（mem 指令）
  //{寄存器冲突时，发送气泡} （变更的寄存器）
  //2，取指令-
  
  wire cpu_reset_n = reset_n && debug_reset_n;
  wire halt = (halt_cpu || halt_debug) && (debug_step_buff2 == debug_step_buff);

  //wire controlByExec = stage2_Valid && stage2_MEMAccess;

  
  //wire [31:0] affect_address    = halt_accept == 1   ? {debug_address[31:2],2'b0}                   : {exec_address[31:2],2'b0};
  wire [31:0] affect_address    = {exec_address[31:2],2'b0};
  //avm_m0_address
  wire [29:0] temp = affect_address[29:0] + private_offset_rear[29:0];
  always @(*) begin
    if(affect_address[31])begin
      if(affect_address[30])begin
        avm_m0_address <= {2'b0,temp};
      end else begin
        avm_m0_address <= {2'b0,affect_address[29:0]} + private_offset;
      end
    end else begin
      avm_m0_address <= affect_address;
    end
  end
  //assign avm_m0_writedata       = halt_accept == 1   ? debug_writedata                              : exec_writedata;
  //assign avm_m0_byteenable      = halt_accept == 1   ? debug_byteenable                             : byteenable;
  //assign avm_m0_write           = halt_accept == 1   ? debug_write                                  : exec_write;
  //assign avm_m0_read            = halt_accept == 1   ? debug_read                                   : exec_read;
  assign avm_m0_writedata       = exec_writedata;
  assign avm_m0_byteenable      = byteenable;
  assign avm_m0_write           = exec_write;
  assign avm_m0_read            = exec_read;

  wire [31:0] fetch_address = preFetch ? preFetchAddr : pc;
  //wire [31:0] affect_addressIns = halt_accept == 1   ? {debug_address[31:2],2'b0}                   : {fetch_address[31:2],2'b0};
  wire [31:0] affect_addressIns = {fetch_address[31:2],2'b0};
  assign avm_m1_address         = affect_addressIns[31] ? {1'b0,affect_addressIns[30:0]} + private_offset : affect_addressIns;
  //assign avm_m1_read            = halt_accept == 1   ? debug_read_ins                               : fetch_read;
  assign avm_m1_read            = fetch_read;

  always @(posedge clk or negedge cpu_reset_n) begin
    if (!cpu_reset_n) begin
      cpu_address <= 0;
    end else begin
      if(avm_m0_write || avm_m0_read)begin
        cpu_address <= avm_m0_address;
      end
      if(avm_m1_read)begin
        cpu_address <= avm_m1_address;
      end
    end
  end

  //reg        latched_high_addr_ins_valid;
  //reg [15:0] latched_high_addr_ins;
  //reg  [9:0] latched_high_addr_index_ins;
  //wire tlb_ins_hold = affect_addressIns[31]==1 && latched_high_addr_ins_valid && latched_high_addr_index_ins == affect_addressIns[19:10];
  //always @(posedge clk or negedge cpu_reset_n) begin
  //  if (!cpu_reset_n) begin
  //    latched_high_addr_ins_valid <= 0;
  //    latched_high_addr_ins <= 0;
  //    latched_high_addr_index_ins <= 0;
  //  end else begin
  //    if(latched_high_addr_index_ins != affect_addressIns[19:10])begin
  //      latched_high_addr_index_ins <= avm_m0_address;
  //      latched_high_addr_ins_valid <= 1;
  //    end
  //    if(avm_m1_read)begin
  //      cpu_address <= avm_m1_address;
  //    end
  //    if(clear_tlb_latch)begin
  //      latched_high_addr_ins_valid <= 0;
  //    end
  //  end
  //end
  //wire tlb_data_hold;
  //tlb: 如果是高地址的话，并且没命中缓存reg，等待flg 置1，命中的话不需要等
  //tlb模块，ins接口 和 data接口
  /*
  2G开始，1M虚拟空间
  页大小：1k Byte

1bit 高2G
11bit dummy
10bit 页表项
10bit 页内偏移

页表大小：2k
每项16bit，寻址64M物理地址，512项

2*m9k，16bit width 1k项 1M虚拟地址

页表miss时要发起中断，保存访问的地址

  */
  `ifdef PC_RECORD
	altsyncram	pc_record (
				.address_a (pc_record_index),
				.clock0 (clk),
				.data_a (pc),
				.wren_a (pushPC),
				.address_b (pc_record_index_read),
				.q_b (pc_record_data),
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clock1 (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_b ({32{1'b1}}),
				.eccstatus (),
				.q_a (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_b (1'b0));
	defparam
		pc_record.address_aclr_b = "NONE",
		pc_record.address_reg_b = "CLOCK0",
		pc_record.clock_enable_input_a = "BYPASS",
		pc_record.clock_enable_input_b = "BYPASS",
		pc_record.clock_enable_output_b = "BYPASS",
		pc_record.intended_device_family = "Cyclone IV E",
		pc_record.lpm_type = "altsyncram",
		pc_record.numwords_a = 256,
		pc_record.numwords_b = 256,
		pc_record.operation_mode = "DUAL_PORT",
		pc_record.outdata_aclr_b = "NONE",
		pc_record.outdata_reg_b = "UNREGISTERED",
		pc_record.power_up_uninitialized = "FALSE",
		pc_record.read_during_write_mode_mixed_ports = "DONT_CARE",
		pc_record.widthad_a = 8,
		pc_record.widthad_b = 8,
		pc_record.width_a = 32,
		pc_record.width_b = 32,
		pc_record.width_byteena_a = 1;
  always @(posedge clk or negedge cpu_reset_n) begin
    if (!cpu_reset_n) begin
      pc_record_index <= 0;
    end else begin
      if(pushPC)begin
        pc_record_index <= pc_record_index + 1'b1;
      end
    end
  end
  `endif
  
  `ifdef DEBUG_STASH
	altsyncram	debug_stash (
				.address_a (debug_stash_index),
				.clock0 (clk),
				.data_a (write_debug_stash_data),
				.wren_a (write_debug_stash),
				.address_b (debug_stash_index_read),
				.q_b (debug_stash_data),
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clock1 (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_b ({32{1'b1}}),
				.eccstatus (),
				.q_a (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_b (1'b0));
	defparam
		debug_stash.address_aclr_b = "NONE",
		debug_stash.address_reg_b = "CLOCK0",
		debug_stash.clock_enable_input_a = "BYPASS",
		debug_stash.clock_enable_input_b = "BYPASS",
		debug_stash.clock_enable_output_b = "BYPASS",
		debug_stash.intended_device_family = "Cyclone IV E",
		debug_stash.lpm_type = "altsyncram",
		debug_stash.numwords_a = 256,
		debug_stash.numwords_b = 256,
		debug_stash.operation_mode = "DUAL_PORT",
		debug_stash.outdata_aclr_b = "NONE",
		debug_stash.outdata_reg_b = "UNREGISTERED",
		debug_stash.power_up_uninitialized = "FALSE",
		debug_stash.read_during_write_mode_mixed_ports = "DONT_CARE",
		debug_stash.widthad_a = 8,
		debug_stash.widthad_b = 8,
		debug_stash.width_a = 32,
		debug_stash.width_b = 32,
		debug_stash.width_byteena_a = 1;
  always @(posedge clk or negedge cpu_reset_n) begin
    if (!cpu_reset_n) begin
      debug_stash_index <= 0;
    end else begin
      if(write_debug_stash)begin
        debug_stash_index <= debug_stash_index + 1'b1;
      end
    end
  end
  `endif
  
  wire predict = 1;
	altsyncram	predict_inst (
				.address_a (write_predict_addr[14:2]),
				.clock0 (clk),
				.data_a (write_predict_val),
				.wren_a (write_predict),
				.address_b (pc[14:2]),
				.q_b (),//predict
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clock1 (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_b ({32{1'b1}}),
				.eccstatus (),
				.q_a (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_b (1'b0));
	defparam
		predict_inst.address_aclr_b = "NONE",
		predict_inst.address_reg_b = "CLOCK0",
		predict_inst.clock_enable_input_a = "BYPASS",
		predict_inst.clock_enable_input_b = "BYPASS",
		predict_inst.clock_enable_output_b = "BYPASS",
		predict_inst.intended_device_family = "Cyclone IV E",
		predict_inst.lpm_type = "altsyncram",
		predict_inst.numwords_a = 8192,
		predict_inst.numwords_b = 8192,
		predict_inst.operation_mode = "DUAL_PORT",
		predict_inst.outdata_aclr_b = "NONE",
		predict_inst.outdata_reg_b = "UNREGISTERED",
		predict_inst.power_up_uninitialized = "FALSE",
		predict_inst.read_during_write_mode_mixed_ports = "DONT_CARE",
		predict_inst.widthad_a = 13,
		predict_inst.widthad_b = 13,
		predict_inst.width_a = 1,
		predict_inst.width_b = 1;

  
  //format0: EC1,IMM26,CMD5
  //format1: EC1,regA5,regB5,IMM16,CMD5
  //format2: EC1,regA5,regB5,regC5,IMM6,CMDEXT5,00000
  //format3: EC1,regA5,regB5,regC5,IMM6,PCEXT5,11111
  wire  [4:0] regA  = avm_m1_readdata[30:26];
  wire  [4:0] regB  = avm_m1_readdata[25:21];
  wire  [4:0] regC  = avm_m1_readdata[20:16];
  wire [25:0] IMM26 = avm_m1_readdata[30:5];
  wire  [5:0] IMM6  = IMM26[10:5];//avm_m1_readdata[15:10];
  wire [15:0] IMM16 = IMM26[15:0];//avm_m1_readdata[20:5];
  wire [31:0] IMM16zx = {16'b0,IMM16};
  wire [31:0] IMM16sx = {{16{IMM16[15]}},IMM16};
  
  wire        parity_check_error = (
              avm_m1_readdata[ 0] ^ avm_m1_readdata[ 1] ^ avm_m1_readdata[ 2]   ^ avm_m1_readdata[ 3] ^
              avm_m1_readdata[ 4] ^ avm_m1_readdata[ 5] ^ avm_m1_readdata[ 6]   ^ avm_m1_readdata[ 7] ^
              avm_m1_readdata[ 8] ^ avm_m1_readdata[ 9] ^ avm_m1_readdata[10]   ^ avm_m1_readdata[11] ^
              avm_m1_readdata[12] ^ avm_m1_readdata[13] ^ avm_m1_readdata[14]   ^ avm_m1_readdata[15] ^
              avm_m1_readdata[16] ^ avm_m1_readdata[17] ^ avm_m1_readdata[18]   ^ avm_m1_readdata[19] ^
              avm_m1_readdata[20] ^ avm_m1_readdata[21] ^ avm_m1_readdata[22]   ^ avm_m1_readdata[23] ^
              avm_m1_readdata[24] ^ avm_m1_readdata[25] ^ avm_m1_readdata[26]   ^ avm_m1_readdata[27] ^
              avm_m1_readdata[28] ^ avm_m1_readdata[29] ^ avm_m1_readdata[30]) == avm_m1_readdata[31];

  reg       PCChange;
  reg       MEMAccess;
  reg       CMP;
  reg       ALU;
  reg       SHIFT1;
  reg       SHIFT2;
  reg       cmd_ext;
  reg [2:0] cmd;
  reg [4:0] regChange;
  always @(*) begin
    PCChange <= 0;
    MEMAccess <= 0;
    CMP <= 0;
    ALU <= 0;
    SHIFT1 <= 0;
    SHIFT2 <= 0;
    cmd_ext <= 0;
    cmd <= avm_m1_readdata[4:2];
    regChange <= regB;//regB
    case(avm_m1_readdata[1:0])
    2'b00 : begin
      if(avm_m1_readdata[4:2]==3'b000)begin//ext
        cmd_ext <= 1;
        cmd <= avm_m1_readdata[9:7];
        regChange <= regC;//regB
        case(avm_m1_readdata[6:5])
          2'b00 : begin
            CMP <= 1;
          end
          2'b01 : begin
            ALU <= 1;
          end
          2'b10 : begin
            SHIFT1 <= 1;
          end
          2'b11 : begin
            SHIFT2 <= 1;
          end
        endcase
      end else begin
        CMP <= 1;
      end
    end
    2'b01 : begin
      ALU <= 1;
    end
    2'b10 : begin
      MEMAccess <= 1;
      regChange <= regB;//MEM的情况下，后续执行逻辑会再变更这个字段
    end
    2'b11 : begin
      if(avm_m1_readdata[4:2]==3'b000)begin//ext
        cmd_ext <= 1;
        cmd <= avm_m1_readdata[9:7];
      end
      PCChange <= 1;
      regChange <= 0;//PC的情况下，后续执行逻辑会再变更这个字段
    end
    endcase
  end
  
  always @(posedge clk or negedge cpu_reset_n) begin
    if (!cpu_reset_n) begin
      performance_ins_count <= 0;
      performance_clk_count <= 0;
    end else begin
      if(performance_count_rst)begin
        performance_ins_count <= 0;
        performance_clk_count <= 0;
      end else begin
        if(performance_count_on)begin
          if(pushPC)begin
            performance_ins_count <= performance_ins_count + 1'b1;
          end
          performance_clk_count <= performance_clk_count + 1'b1;
        end
      end
    end
  end

  reg        latch1_PCChange          ;
  reg        latch1_MEMAccess         ;
  reg        latch1_CMP               ;
  reg        latch1_ALU               ;
  reg        latch1_SHIFT1            ;
  reg        latch1_SHIFT2            ;
  reg        latch1_cmd_ext           ;
  reg        latch1_parity_check_error;
  reg [2:0]  latch1_cmd               ;
  reg [4:0]  latch1_regChange         ;
  reg [4:0]  latch1_regA              ;
  reg [4:0]  latch1_regB              ;
  reg [4:0]  latch1_regC              ;
  reg [25:0] latch1_IMM26             ;
  wire [5:0]  latch1_IMM6  = latch1_IMM26[10:5];//avm_m1_readdata[15:10];
  wire [15:0] latch1_IMM16 = latch1_IMM26[15:0];//avm_m1_readdata[20:5];
  wire [31:0] latch1_IMM16zx = {16'b0,latch1_IMM16};
  wire [31:0] latch1_IMM16sx = {{16{latch1_IMM16[15]}},latch1_IMM16};
  
  
  reg         pushPC;
  wire [31:0] nextpc = {{pc[31:2] + 1'b1},2'b0};
  reg   [1:0] latch1_readdata10;
  reg         irq_req_buff;
  reg         fetch_read;
  reg   [1:0] fetch_status;
  reg         debug_step_buff;
  reg         debug_step_buff2;
  reg         halt_accept;
  reg         preFetch;
  reg  [31:0] preFetchAddr;
  reg         write_predict;
  reg  [31:0] write_predict_addr;
  reg         write_predict_val;

  wire fetch_wait_1 = //holdStage || stage1_Valid || stage2_Valid;
              (holdStage && stage1_Valid) ||
              (stage1_Valid && stage1_regChange != 5'b0 && (stage1_regChange == regA || stage1_regChange == regB)) ||
              (stage2_Valid && stage2_regChange != 5'b0 && (stage2_regChange == regA || stage2_regChange == regB));
  wire fetch_wait_2 = //holdStage || stage1_Valid || stage2_Valid;
              (holdStage && stage1_Valid) ||
              (stage1_Valid && stage1_regChange != 5'b0 && (stage1_regChange == latch1_regA || stage1_regChange == latch1_regB)) ||
              (stage2_Valid && stage2_regChange != 5'b0 && (stage2_regChange == latch1_regA || stage2_regChange == latch1_regB));
  always @(posedge clk or negedge cpu_reset_n) begin
    if (!cpu_reset_n) begin
      //stage1寄存器初始化
      stage1_Valid <= 0;
      stage1_PCChange <= 0;
      stage1_MEMAccess <= 0;
      fetch_status <= 0;
      `ifdef isALTERA
      pc<=32'h4000_0000;// ###############################################################################################################
      `endif
      `ifdef isVIVADO
      pc<=32'h0000_0000;// ###############################################################################################################
      `endif
      irq_req_buff <= 0;
      debug_step_buff <= 0;
      debug_step_buff2 <= 0;
      curr_data <= 0;
      pushPC <= 0;
      stage1_regA <= 0;
      stage1_irq <= 0;
      halt_cpu <= 0;
      preFetch <= 0;
      write_predict <= 0;
    end else begin
      irq_req_buff <= irq_req;
      pushPC <= 0;
      stage1_irq <= 0;
      write_predict <= 0;
      
      //流水线里有pc，mem指令时，fetch关闭
      if(!holdStage)begin
        stage1_Valid <= 0;
      end
      case(fetch_status)
      0:begin
        if(halt)begin
          halt_accept <= 1;
          {stage1_irq, stage1_regA} <= debug_regAddr;//(halt_accept || force_halt) ? debug_regAddr : stage1_regA
        end else begin
          debug_step_buff <= debug_step;
          debug_step_buff2 <= debug_step_buff;
          halt_accept <= 0;
          if(irq_req_buff && irq_enable)begin
            if(holdStage ||
              stage1_Valid ||
              stage2_Valid ||
              stage3_Valid
            )begin
            end else begin
              //r29 ea Exception return address
              stage1_Valid <= 1;
              stage1_PCChange <= 1;
              stage1_MEMAccess <= 0;
              stage1_CMP <= 0;
              stage1_ALU <= 0;
              stage1_SHIFT1 <= 0;
              stage1_SHIFT2 <= 0;
              stage1_cmd_ext <= 1;
              //stage1_cmd <= 3'b111;
              stage1_cmd <= 3'b011;
              stage1_regC <= 29;
              stage1_regA <= irq_id;
              stage1_irq <= 1'b1;
              fetch_status <= 3;
            end
          end else begin
            fetch_read <= 1;
            fetch_status <= 1;
          end
        end
      end
      1:begin//wait fetch
        if(!avm_m1_waitrequest)begin
          if(preFetch)begin
            preFetch <= 0;
          end
          fetch_read <= 0;
          //发送指令前判断寄存器冲突
          if(fetch_wait_1)begin
            //latch_readdata <= avm_m1_readdata;
            fetch_status <= 2;//响应后，如果不能发射指令，预取下一条指令, 当前数据进锁存，状态=>2
            
            case(avm_m1_readdata[1:0])
            2'b00,2'b01,2'b10 : begin
              if(halt || irq_req_buff && irq_enable)begin
              end else begin
                // 预取下一条指令
                fetch_read <= 1;
              end
              pc <= nextpc; pushPC <= 1;
            end
            2'b11 : begin
            end
            endcase

            
            latch1_readdata10 <= avm_m1_readdata[1:0];

            latch1_PCChange           <= PCChange           ;
            latch1_MEMAccess          <= MEMAccess          ;
            latch1_CMP                <= CMP                ;
            latch1_ALU                <= ALU                ;
            latch1_SHIFT1             <= SHIFT1             ;
            latch1_SHIFT2             <= SHIFT2             ;
            latch1_cmd_ext            <= cmd_ext            ;
            latch1_cmd                <= cmd                ;
            latch1_regChange          <= regChange          ;
            latch1_parity_check_error <= parity_check_error ;
            latch1_regA               <= regA               ;
            latch1_regB               <= regB               ;
            latch1_regC               <= regC               ;
            latch1_IMM26              <= IMM26              ;

          end else begin
            case(avm_m1_readdata[1:0])
            2'b00,2'b01,2'b10 : begin
              if(halt || irq_req_buff && irq_enable)begin
                fetch_status <= 0;
              end else begin
                fetch_read <= 1;
                fetch_status <= 1;
              end
              pc <= nextpc;pushPC <= 1;
            end
            2'b11 : begin
              fetch_status <= 3;//update pc
              preFetchAddr <= predict ? (nextpc + IMM16sx) : nextpc;
              //if(stage1_PCChange)begin
              if(cmd_ext == 0)begin
                //031628 -> 031459
                //call sym                     @          22 @                      2 @  000111
                //3'b001 : begin//ok
                case(cmd)
                //#pc ext                                                                00011
                3'b000 : begin//ok
                end
                //call sym                     @          22 @                      2 @  000111
                3'b001 : begin//ok
                  pc <= {pc[31:28],IMM26,2'b00};
                  pushPC <= 1;
                  if(halt || irq_req_buff && irq_enable)begin
                    fetch_status <= 0;
                  end else begin
                    fetch_read <= 1;
                    fetch_status <= 1;
                  end
                end
                //bge reg, reg, sym            @          15 @                      0 @  001111
                3'b010 : begin//ok
                  preFetch <= 1;
                  fetch_read <= 1;
                end
                //blt reg, reg, sym            @          15 @                      0 @  010111
                3'b011 : begin//ok
                  preFetch <= 1;
                  fetch_read <= 1;
                end
                //bne reg, reg, sym            @          15 @                      0 @  011111
                3'b100 : begin//ok
                  preFetch <= 1;
                  fetch_read <= 1;
                end
                //beq reg, reg, sym            @          15 @                      0 @  100111
                3'b101 : begin//ok
                  if(regA == regB)begin
                    pc <= nextpc + IMM16sx;
                    pushPC <= 1;
                    if(halt || irq_req_buff && irq_enable)begin
                      fetch_status <= 0;
                    end else begin
                      fetch_read <= 1;
                      fetch_status <= 1;
                    end
                  end else begin
                  preFetch <= 1;
                  fetch_read <= 1;
                  end
                end
                //bgeu reg, reg, sym           @          15 @                      0 @  101111
                3'b110 : begin//ok
                  preFetch <= 1;
                  fetch_read <= 1;
                end
                //bltu reg, reg, sym           @          15 @                      0 @  110111
                3'b111 : begin//ok
                  preFetch <= 1;
                  fetch_read <= 1;
                end
                endcase
              end else begin
                //hlt ins                      @          54 @                      1 @  111111
                if(cmd == 3'b100) begin//ok
                  pc <= nextpc;
                  pushPC <= 1;
                  halt_cpu <= IMM6[0];
                  fetch_status <= 0;
                end
                if(parity_check_error) begin
                  halt_cpu <= 1;
                  fetch_status <= 0;
                end
              end
              //end
            end
            endcase
            stage1_Valid <= 1;
            

            stage1_PCChange           <= PCChange           ;
            stage1_MEMAccess          <= MEMAccess          ;
            stage1_CMP                <= CMP                ;
            stage1_ALU                <= ALU                ;
            stage1_SHIFT1             <= SHIFT1             ;
            stage1_SHIFT2             <= SHIFT2             ;
            stage1_cmd_ext            <= cmd_ext            ;
            stage1_cmd                <= cmd                ;
            stage1_regChange          <= regChange          ;
            stage1_parity_check_error <= parity_check_error ;
            stage1_regA               <= regA               ;
            stage1_regB               <= regB               ;
            stage1_regC               <= regC               ;
            stage1_IMM26              <= IMM26              ;
            stage1_nextpc             <= nextpc;
          end
          
          //curr_data <= avm_m1_readdata;

        end
      end
      2:begin// 
        if(!avm_m1_waitrequest)begin
          fetch_read <= 0;
        end

        if(fetch_wait_2)begin
          fetch_status <= 2;
        end else begin
          //可以发射指令，发射指令，状态->1
          stage1_Valid <= 1;
          case(latch1_readdata10)
          2'b00,2'b01,2'b10 : begin
            if(halt || irq_req_buff && irq_enable)begin
              stage1_Valid <= 0;
              if(!avm_m1_waitrequest)begin
                fetch_status <= 0;
                stage1_Valid <= 1;
              end
            end else begin
              fetch_status <= 1;
            end
          end
          2'b11 : begin
            fetch_status <= 3;//update pc
            //030653 -> 030150
            //+060548564 +0192563165 +02545485 nextpc vs 
            //+060548564 +0190355684 +02516643 predict
            preFetchAddr <= predict ? (nextpc + latch1_IMM16sx) : nextpc;
            //if(stage1_PCChange)begin
            if(latch1_cmd_ext == 0)begin
              //call sym                     @          22 @                      2 @  000111
              //3'b001 : begin//ok
              case(latch1_cmd)
              //#pc ext                                                                00011
              3'b000 : begin//ok
              end
              //call sym                     @          22 @                      2 @  000111
              3'b001 : begin//ok
                pc <= {pc[31:28],latch1_IMM26,2'b00};
                pushPC <= 1;
                if(halt || irq_req_buff && irq_enable)begin
                  fetch_status <= 0;
                end else begin
                  fetch_read <= 1;
                  fetch_status <= 1;
                end
              end
              //bge reg, reg, sym            @          15 @                      0 @  001111
              3'b010 : begin//ok
                preFetch <= 1;
                fetch_read <= 1;
              end
              //blt reg, reg, sym            @          15 @                      0 @  010111
              3'b011 : begin//ok
                preFetch <= 1;
                fetch_read <= 1;
              end
              //bne reg, reg, sym            @          15 @                      0 @  011111
              3'b100 : begin//ok
                preFetch <= 1;
                fetch_read <= 1;
              end
              //beq reg, reg, sym            @          15 @                      0 @  100111
              3'b101 : begin//ok
                if(latch1_regA == latch1_regB)begin
                  pc <= nextpc + latch1_IMM16sx;
                  pushPC <= 1;
                  if(halt || irq_req_buff && irq_enable)begin
                    fetch_status <= 0;
                  end else begin
                    fetch_read <= 1;
                    fetch_status <= 1;
                  end
                end else begin
                  preFetch <= 1;
                  fetch_read <= 1;
                end
              end
              //bgeu reg, reg, sym           @          15 @                      0 @  101111
              3'b110 : begin//ok
                preFetch <= 1;
                fetch_read <= 1;
              end
              //bltu reg, reg, sym           @          15 @                      0 @  110111
              3'b111 : begin//ok
                preFetch <= 1;
                fetch_read <= 1;
              end
              endcase
            end else begin
              //hlt ins                      @          54 @                      1 @  111111
              if(latch1_cmd == 3'b100) begin//ok
                pc <= nextpc;
                pushPC <= 1;
                halt_cpu <= latch1_IMM6[0];
                fetch_status <= 0;
              end
              if(latch1_parity_check_error) begin
                halt_cpu <= 1;
                fetch_status <= 0;
              end
            end
            //end
          end
          endcase

          stage1_PCChange           <= latch1_PCChange           ;
          stage1_MEMAccess          <= latch1_MEMAccess          ;
          stage1_CMP                <= latch1_CMP                ;
          stage1_ALU                <= latch1_ALU                ;
          stage1_SHIFT1             <= latch1_SHIFT1             ;
          stage1_SHIFT2             <= latch1_SHIFT2             ;
          stage1_cmd_ext            <= latch1_cmd_ext            ;
          stage1_parity_check_error <= latch1_parity_check_error ;
          stage1_cmd                <= latch1_cmd                ;
          stage1_regChange          <= latch1_regChange          ;
          stage1_regA               <= latch1_regA               ;
          stage1_regB               <= latch1_regB               ;
          stage1_regC               <= latch1_regC               ;
          stage1_IMM26              <= latch1_IMM26              ;
          stage1_nextpc             <= nextpc;

        end
      end
      3:begin//wait rw
        if(preFetch)begin
          if(!avm_m1_waitrequest)begin
            preFetch <= 0;
            fetch_read <= 0;
          end
          if(stage1_Valid)begin// || stage2_Valid
            //等待
          end else begin
            if(preFetchAddr == {pcResult[31:2],2'b0})begin
              //预测成功
              fetch_status <= 1;
              pc <= {pcResult[31:2],2'b0};
              pushPC <= 1;
            end else begin
              //预测失败
              if(!avm_m1_waitrequest)begin
                pc <= {pcResult[31:2],2'b0};
                pushPC <= 1;
                write_predict <= 1;
                write_predict_addr <= pc;
                write_predict_val <= !predict;
                preFetch <= 0;
                if(halt || irq_req_buff && irq_enable)begin
                  fetch_status <= 0;
                end else begin
                  fetch_read <= 1;
                  fetch_status <= 1;
                end
              end
            end
          end
        end else begin
          if(stage1_Valid)begin// || stage2_Valid
            //等待
          end else begin
            pc <= {pcResult[31:2],2'b0};
            pushPC <= 1;
            if(halt || irq_req_buff && irq_enable)begin
              fetch_status <= 0;
            end else begin
              fetch_read <= 1;
              fetch_status <= 1;
            end
          end
        end
      end
      endcase
    end
  end


  reg         stage1_Valid;
  reg         stage1_PCChange;
  reg         stage1_MEMAccess;
  reg         stage1_CMP;
  reg         stage1_ALU;
  reg         stage1_SHIFT1;
  reg         stage1_SHIFT2;
  reg         stage1_cmd_ext;
  reg         stage1_parity_check_error;
  reg [2:0]   stage1_cmd;
  reg [4:0]   stage1_regChange;
  reg [4:0]   stage1_regA;
  reg [4:0]   stage1_regB;
  reg [4:0]   stage1_regC;
  reg [25:0]  stage1_IMM26;
  wire [5:0]  stage1_IMM6  = stage1_IMM26[10:5];//avm_m1_readdata[15:10];
  wire [15:0] stage1_IMM16 = stage1_IMM26[15:0];//avm_m1_readdata[20:5];
  reg         stage1_irq;
  reg [31:0]  stage1_nextpc;
  wire [31:0] stage1_IMM16zx = {16'b0,stage1_IMM16};
  wire [31:0] stage1_IMM16sx = {{16{stage1_IMM16[15]}},stage1_IMM16};
  wire [31:0] regDataOutA = reg_outA;
  wire [31:0] regDataOutB = reg_outB;
  
  //3，stage1 取寄存器/乘法移位预处理
  always @(posedge clk or negedge cpu_reset_n) begin
    if (!cpu_reset_n) begin
      //stage2寄存器初始化
      stage2_Valid <= 0;
    end else begin

      if(!holdStage)begin
        stage2_Valid <= 0;
        if(!stage1_Valid)begin
          if(halt_accept)begin
            if(debug_rw)begin
              stage2_Valid <= 1;
              stage2_regChange <= 0;
              stage2_PCChange  <= 0;
              stage2_MEMAccess <= 1;
              stage2_CMP       <= 0;
              stage2_ALU       <= 0;
              stage2_SHIFT1    <= 0;
              stage2_SHIFT2    <= 0;
              stage2_cmd_ext <= 0;
              stage2_cmd <= debug_rw_cmd;
              stage2_regfileA <= debug_address;
              stage2_regfileB <= debug_writedata;
              stage2_IMM26 <= 0;
            end
          end
        
        end else begin
          stage2_Valid <= 1;
          stage2_nextpc <= stage1_nextpc;

          stage2_PCChange  <= stage1_PCChange   ;
          stage2_MEMAccess <= stage1_MEMAccess  ;
          stage2_CMP       <= stage1_CMP        ;
          stage2_ALU       <= stage1_ALU        ;
          stage2_SHIFT1    <= stage1_SHIFT1     ;
          stage2_SHIFT2    <= stage1_SHIFT2     ;
          stage2_cmd_ext   <= stage1_cmd_ext    ;
          stage2_cmd       <= stage1_cmd        ;
          //stage2_regA      <= stage1_regA       ;
          //stage2_regB      <= stage1_regB       ;
          stage2_regC      <= stage1_regC       ;
          stage2_IMM26     <= stage1_IMM26      ;
          stage2_regfileA  <= regDataOutA       ;
          stage2_regfileB  <= regDataOutB       ;
          //stage2_parity_check_error <= stage1_parity_check_error;

          if(stage1_MEMAccess)begin
            case(stage1_cmd)
              //ldw reg, regins              @          11 @                      0 @   7 @          000111      0x07 ldw rB, byte_offset(rA)
              3'b000 : begin//ok
                stage2_regChange <= stage1_regB;//regB
              end
              //stw reg, regins              @          11 @                      0 @  15 @          001111      0x0f stw rB, byte_offset(rA)
              3'b001 : begin//ok
                stage2_regChange <= 0;
              end
              //ldbu reg, regins             @          11 @                      0 @  23 @          010111      0x17
              3'b010 : begin//ok
                stage2_regChange <= stage1_regB;//regB
              end
              //ldb reg, regins              @          11 @                      0 @  31 @          011111      0x1f*
              3'b011 : begin//ok
                stage2_regChange <= stage1_regB;//regB
              end
              //ldhu reg, regins             @          11 @                      0 @  39 @          100111      0x27
              3'b100 : begin//ok
                stage2_regChange <= stage1_regB;//regB
              end
              //ldh reg, regins              @          11 @                      0 @  47 @          101111      0x2f
              3'b101 : begin//ok
                stage2_regChange <= stage1_regB;//regB
              end
              //stb reg, regins              @          11 @                      0 @  55 @          110111      0x37*
              3'b110 : begin//ok
                stage2_regChange <= 0;
              end
              //sth reg, regins              @          11 @                      0 @  63 @          111111      0x3f*
              3'b111 : begin//ok
                stage2_regChange <= 0;
              end
            endcase
          end else begin
            stage2_regChange <= stage1_regChange;
          end
          //#01 alu
          //muli reg, reg, ins           @          10 @                      0 @  10001
          //#01 alu ext
          //mul reg, reg, reg            @          30 @                      1 @  10001
          //if(stage1_ALU && stage1_cmd==3'b100)begin
          //if(stage1_cmd_ext)begin
          //  mulDataB <= regDataOutB;
          //end else begin
          //  mulDataB <= stage1_IMM16sx;
          //end
          //end

          //if(stage1_SHIFT1)begin
          //  shiftDistance <= stage1_IMM6[4:0];
          //end else begin //if(stage1_SHIFT2)begin
          //  shiftDistance <= regDataOutB[4:0];
          //end

          //#10 shift1
          //#11 shift2
//          case(stage1_cmd[1:0])
//          //slli reg, reg, ins            @         31 @                      1 @  00010
//          //sll reg, reg, reg            @          30 @                      1 @  00011
//          2'b00 : begin
//            shiftDirection <= 0;//0:left 1:right
//          end
//          //srai reg, reg, ins            @         31 @                      1 @  00110
//          //sra reg, reg, reg            @          30 @                      1 @  00111
//          2'b01 : begin
//            shiftDirection <= 1;//0:left 1:right
//          end
//          //srli reg, reg, ins            @         31 @                      1 @  01010
//          //srl reg, reg, reg            @          30 @                      1 @  01011
//          2'b10 : begin
//            shiftDirection <= 1;//0:left 1:right
//          end
//          //roli reg, reg, ins            @         31 @                      1 @  01110
//          //rol reg, reg, reg            @          30 @                      1 @  01111
//          2'b11 : begin
//            shiftDirection <= 0;//0:left 1:right
//          end
//          endcase


          //stage2_CMP
          //cmpgei reg, reg, ins         @          10 @                      0 @  001000
          stage2_res_cmpgei <= ($signed(regDataOutA) >= $signed(stage1_IMM16sx)); //if ((signed) rA >= (signed) σ(IMM16)) then rB ← 1 else rB ← 0
          //cmplti reg, reg, ins         @          10 @                      0 @  010000
          //stage2_res_cmplti <= !stage2_res_cmpgei;//($signed(regDataOutA) < $signed(stage1_IMM16sx)); //if ((signed) rA < (signed) σ(IMM16))
          //cmpnei reg, reg, ins         @          10 @                      0 @  011000
          //stage2_res_cmpnei <= (regDataOutA != stage1_IMM16sx); //if (rA != σ(IMM16)) then rB ← 1 else rB ← 0
          //cmpeqi reg, reg, ins         @          10 @                      0 @  100000
          //stage2_res_cmpeqi <= !stage2_res_cmpnei;//(regDataOutA == stage1_IMM16sx); //if (rA == σ(IMM16)) then rB ← 1 else rB ← 0
          //cmpgeui reg, reg, ins        @          10 @                      0 @  101000
          stage2_res_cmpgeui <= (regDataOutA >= stage1_IMM16zx); //if ((unsigned) rA >= (unsigned) (0x0000 : IMM16)) then rB ← 1 else rB ← 0
          //cmpltui reg, reg, ins        @          10 @                      0 @  110000
          //stage2_res_cmpltui <= !stage2_res_cmpgeui;//(regDataOutA < stage1_IMM16zx); //if ((unsigned) rA < (unsigned) (0x0000 : IMM16)) then rB ← 1 else rB ← 0

          //cmpge reg, reg, reg          @          30 @                      3 @  001100
          stage2_res_cmpge <= ($signed(regDataOutA) >= $signed(regDataOutB)); // if ((signed) rA >= (signed) rB) then rC ← 1  else rC ← 0
          //cmplt reg, reg, reg          @          30 @                      3 @  010100
          //stage2_res_cmplt <= !stage2_res_cmpge;//($signed(regDataOutA)<$signed(regDataOutB)); //if ((signed) rA < (signed) rB) then rC ← 1 else rC ← 0
          //cmpne reg, reg, reg          @          30 @                      3 @  011100
          //stage2_res_cmpne <= (regDataOutA!=regDataOutB); //if (rA != rB) then rC ← 1 else rC ← 0
          //cmpeq reg, reg, reg          @          30 @                      3 @  100100
          //stage2_res_cmpeq <= !stage2_res_cmpne;//(regDataOutA==regDataOutB); //if (rA == rB) then rC ← 1 else rC ← 0
          //#cmpgeu reg, reg, reg         @          30 @                      3 @  101100
          stage2_res_cmpgeu <= (regDataOutA >= regDataOutB); //if (rA == rB) then rC ← 1 else rC ← 0
          //cmpltu reg, reg, reg         @          30 @                      3 @  110100
          //stage2_res_cmpltu <= !stage2_res_cmpgeu;//(regDataOutA < regDataOutB); //if ((unsigned) rA < (unsigned) rB) then rC ← 1 else rC ← 0


          //stage2_ALU
          //addi reg, reg, ins           @          10 @                      0 @  000010
          //stage2_res_addi <= regDataOutA + stage1_IMM16sx; //rB ← rA + σ(IMM16)
          //andi reg, reg, ins           @          10 @                      0 @  001010
          //stage2_res_andi <= {16'b0, (regDataOutA[15:0] & stage1_IMM16)}; //rB ← rA & (0x0000 : IMM16)
          //ori  reg, reg, ins           @          10 @                      0 @  010010
          //stage2_res_ori <= {regDataOutA[31:16],(regDataOutA[15:0] | stage1_IMM16)}; //rB ← rA | (0x0000 : IMM16)
          //xori reg, reg, ins           @          10 @                      0 @  011010
          //stage2_res_xori <= {regDataOutA[31:16], (regDataOutA[15:0] ^ stage1_IMM16)}; //rB ← rA ^ (0x0000 : IMM16)
          //#                                                                      100010
          //andhi reg, reg, ins          @          10 @                      0 @  101010
          //stage2_res_andhi <= {(regDataOutA[31:16] & stage1_IMM16), 16'b0}; //rB ← rA & (IMM16 : 0x0000)
          //orhi reg, reg, ins           @          10 @                      0 @  110010
          //stage2_res_orhi <= {(regDataOutA[31:16] | stage1_IMM16),regDataOutA[15:0]}; //rB ← rA | (IMM16 : 0x0000)
          //xorhi reg, reg, ins          @          10 @                      0 @  111010
          //stage2_res_xorhi <= {(regDataOutA[31:16] ^ stage1_IMM16), regDataOutA[15:0]}; //rB ← rA ^ (IMM16 : 0x0000)

          //add reg, reg, reg            @          30 @                      1 @  000110
          stage2_res_add <= regDataOutA + (stage1_cmd_ext ? regDataOutB : stage1_IMM16sx); //rC ← rA + rB
          //and reg, reg, reg            @          30 @                      1 @  001110
          //stage2_res_and <= regDataOutA & (stage1_cmd_ext ? regDataOutB : stage1_IMM16zx); // rC ← rA | rB
          //or reg, reg, reg             @          30 @                      1 @  010110
          //stage2_res_or <= regDataOutA | (stage1_cmd_ext ? regDataOutB : stage1_IMM16zx); // rC ← rA | rB
          //xor reg, reg, reg            @          30 @                      1 @  011110
          //stage2_res_xor <= regDataOutA ^ (stage1_cmd_ext ? regDataOutB : stage1_IMM16zx); // rC ← rA ^ rB
          //sub reg, reg, reg            @          30 @                      1 @  100110
          if(stage1_cmd_ext)begin
            stage2_res_sub_andhi <= regDataOutA - regDataOutB; // rC ← rA – rB
            //stage2_res_nor_orhi <= ~(regDataOutA | regDataOutB); // rC ← ~(rA | rB)
          end else begin
            stage2_res_sub_andhi <= {(regDataOutA[31:16] & stage1_IMM16), 16'b0}; //rB ← rA & (IMM16 : 0x0000)
            //stage2_res_nor_orhi <= {(regDataOutA[31:16] | stage1_IMM16),regDataOutA[15:0]}; //rB ← rA | (IMM16 : 0x0000)
          end
          //nor reg, reg, reg            @          30 @                      1 @  101110

        end
      end
    end
  end
  reg         stage2_Valid;
  reg         stage2_PCChange;
  reg         stage2_MEMAccess;
  reg         stage2_CMP;
  reg         stage2_ALU;
  reg         stage2_SHIFT1;
  reg         stage2_SHIFT2;
  reg         stage2_cmd_ext;
  //reg         stage2_parity_check_error;
  reg [2:0]   stage2_cmd;
  reg [4:0]   stage2_regChange;
  //reg [4:0]  stage2_regA;
  //reg [4:0]  stage2_regB;
  reg [4:0]   stage2_regC;
  reg [25:0]  stage2_IMM26;
  wire [15:0] stage2_IMM16 = stage2_IMM26[15:0];//avm_m1_readdata[20:5];
  wire  [5:0] stage2_IMM6  = stage2_IMM26[10:5];//avm_m1_readdata[15:10];
  wire [31:0] stage2_IMM16zx = {16'b0,stage2_IMM16};
  wire [31:0] stage2_IMM16sx = {{16{stage2_IMM16[15]}},stage2_IMM16};
  reg [31:0]  stage2_regfileA;
  reg [31:0]  stage2_regfileB;
  reg [31:0]  stage2_nextpc;
  //其他计算好的前级
  reg        shiftDirection;
  always @(*) begin
    case(stage2_cmd[1:0])
    //slli reg, reg, ins            @         31 @                      1 @  00010
    //sll reg, reg, reg            @          30 @                      1 @  00011
    2'b00 : begin
      shiftDirection <= 0;//0:left 1:right
    end
    //srai reg, reg, ins            @         31 @                      1 @  00110
    //sra reg, reg, reg            @          30 @                      1 @  00111
    2'b01 : begin
      shiftDirection <= 1;//0:left 1:right
    end
    //srli reg, reg, ins            @         31 @                      1 @  01010
    //srl reg, reg, reg            @          30 @                      1 @  01011
    2'b10 : begin
      shiftDirection <= 1;//0:left 1:right
    end
    //roli reg, reg, ins            @         31 @                      1 @  01110
    //rol reg, reg, reg            @          30 @                      1 @  01111
    2'b11 : begin
      shiftDirection <= 0;//0:left 1:right
    end
    endcase
  end
  
  wire [4:0] shiftDistance = stage2_SHIFT1 ? stage2_IMM6[4:0] : stage2_regfileB[4:0];

          //stage2_CMP
          //cmpgei reg, reg, ins         @          10 @                      0 @  001000
reg stage2_res_cmpgei;
          //cmplti reg, reg, ins         @          10 @                      0 @  010000
wire stage2_res_cmplti = !stage2_res_cmpgei;
          //cmpnei reg, reg, ins         @          10 @                      0 @  011000
wire stage2_res_cmpnei = (stage2_regfileA != stage2_IMM16sx);
          //cmpeqi reg, reg, ins         @          10 @                      0 @  100000
wire stage2_res_cmpeqi = !stage2_res_cmpnei;
          //cmpgeui reg, reg, ins        @          10 @                      0 @  101000
reg stage2_res_cmpgeui;
          //cmpltui reg, reg, ins        @          10 @                      0 @  110000
wire stage2_res_cmpltui = !stage2_res_cmpgeui;

          //cmpge reg, reg, reg          @          30 @                      3 @  001100
reg stage2_res_cmpge;
          //cmplt reg, reg, reg          @          30 @                      3 @  010100
wire stage2_res_cmplt = !stage2_res_cmpge;
          //cmpne reg, reg, reg          @          30 @                      3 @  011100
wire stage2_res_cmpne = stage2_regfileA != stage2_regfileB;
          //cmpeq reg, reg, reg          @          30 @                      3 @  100100
wire stage2_res_cmpeq = !stage2_res_cmpne;
          //#cmpgeu reg, reg, reg         @          30 @                      3 @  101100
reg stage2_res_cmpgeu;
          //cmpltu reg, reg, reg         @          30 @                      3 @  110100
wire stage2_res_cmpltu = !stage2_res_cmpgeu;

          //stage2_ALU2
          //addi reg, reg, ins           @          10 @                      0 @  000010
//reg [31:0] stage2_res_addi;
          //andi reg, reg, ins           @          10 @                      0 @  001010
//reg [31:0] stage2_res_andi;
          //ori  reg, reg, ins           @          10 @                      0 @  010010
//reg [31:0] stage2_res_ori;
          //xori reg, reg, ins           @          10 @                      0 @  011010
//reg [31:0] stage2_res_xori;
          //#                                                                      100010
          //andhi reg, reg, ins          @          10 @                      0 @  101010
//reg [31:0] stage2_res_andhi;
          //orhi reg, reg, ins           @          10 @                      0 @  110010
//reg [31:0] stage2_res_orhi;
          //xorhi reg, reg, ins          @          10 @                      0 @  111010
wire [31:0] stage2_res_xorhi = {(stage2_regfileA[31:16] ^ stage2_IMM16), stage2_regfileA[15:0]};

          //add reg, reg, reg            @          30 @                      1 @  000110
reg [31:0] stage2_res_add;
          //and reg, reg, reg            @          30 @                      1 @  001110
wire [31:0] stage2_res_and = stage2_regfileA & (stage2_cmd_ext ? stage2_regfileB : stage2_IMM16zx); // rC ← rA | rB
          //or reg, reg, reg             @          30 @                      1 @  010110
wire [31:0] stage2_res_or = stage2_regfileA | (stage2_cmd_ext ? stage2_regfileB : stage2_IMM16zx); // rC ← rA | rB
          //xor reg, reg, reg            @          30 @                      1 @  011110
wire [31:0] stage2_res_xor = stage2_regfileA ^ (stage2_cmd_ext ? stage2_regfileB : stage2_IMM16zx); // rC ← rA ^ rB
          //sub reg, reg, reg            @          30 @                      1 @  100110
reg [31:0] stage2_res_sub_andhi;
          //nor reg, reg, reg            @          30 @                      1 @  101110
wire [31:0] stage2_res_nor_orhi = stage1_cmd_ext ? ~(stage2_regfileA | stage2_regfileB) : {(stage2_regfileA[31:16] | stage2_IMM16),stage2_regfileA[15:0]}; //rB ← rA | (IMM16 : 0x0000)


wire [31:0] stage2_byteclip_int = stage2_regfileB[31] ? 0 : (stage2_regfileB[30:8] ? 255 : stage2_regfileB[7:0]);
wire [31:0] stage2_byteclip_short = stage2_regfileB[15] ? 0 : (stage2_regfileB[14:8] ? 255 : stage2_regfileB[7:0]);

wire [31:0] stage2_regfileB_byteclip = stage2_IMM6[3] ? stage2_byteclip_short : stage2_byteclip_int;

wire [31:0] rgbval = stage2_IMM6[2] ? stage2_regfileB_byteclip : stage2_regfileB;

wire [4:0] red = rgbval[7:3];//setr
wire [5:0] green = rgbval[7:2];//setg
wire [4:0] blue = rgbval[7:3];//setb
wire [31:0] stage2_setRGB_r = {16'b0,red,stage2_regfileA[10:0]};//setr
wire [31:0] stage2_setRGB_g = {16'b0,stage2_regfileA[15:11],green,stage2_regfileA[4:0]};//setg
wire [31:0] stage2_setRGB_b = {16'b0,stage2_regfileA[15:5],blue};//setb
wire [31:0] stage2_setRGB_rgb = {16'b0,stage2_regfileB[23:19],stage2_regfileB[15:10],stage2_regfileB[7:3]};//setrgb

  
  //////////////////////////////////////////////////////////

`ifdef SHIFT_IP
  wire [31:0]  shiftResultLogical;
  lpm_clshift	shiftLogical_inst (
    .data (stage2_regfileA),
    .direction (shiftDirection),
    .distance (shiftDistance),
    .result (shiftResultLogical)
    );
  defparam
    shiftLogical_inst.lpm_shifttype = "LOGICAL",
    shiftLogical_inst.lpm_type = "LPM_CLSHIFT",
    shiftLogical_inst.lpm_width = 32,
    shiftLogical_inst.lpm_widthdist = 5;

  wire [31:0]  shiftResultArithmetic;
  lpm_clshift	shiftArithmetic_inst (
    .data (stage2_regfileA),
    .direction (shiftDirection),
    .distance (shiftDistance),
    .result (shiftResultArithmetic)
    );
  defparam
    shiftArithmetic_inst.lpm_shifttype = "ARITHMETIC",
    shiftArithmetic_inst.lpm_type = "LPM_CLSHIFT",
    shiftArithmetic_inst.lpm_width = 32,
    shiftArithmetic_inst.lpm_widthdist = 5;
  
  
  wire [31:0]  shiftResultRotate;
  lpm_clshift	shiftRotate_inst (
    .data (stage2_regfileA),
    .direction (shiftDirection),
    .distance (shiftDistance),
    .result (shiftResultRotate)
    );
  defparam
    shiftRotate_inst.lpm_shifttype = "ROTATE",
    shiftRotate_inst.lpm_type = "LPM_CLSHIFT",
    shiftRotate_inst.lpm_width = 32,
    shiftRotate_inst.lpm_widthdist = 5;
`else
  reg [31:0]  shiftResultLogical;
  reg [31:0]  shiftResultArithmetic;
  reg [31:0]  shiftResultRotate;
  always @(*) begin
    if(shiftDirection==0)begin//0:left * 1:right /
      case(shiftDistance)
      0 : begin shiftResultLogical <= {shiftDataIn[31: 0]      };shiftResultArithmetic <= {                   shiftDataIn[31:0]      };shiftResultRotate <= {shiftDataIn[31: 0]                   }; end
      1 : begin shiftResultLogical <= {shiftDataIn[30: 0], 1'b0};shiftResultArithmetic <= {                   shiftDataIn[30:0], 1'b0};shiftResultRotate <= {shiftDataIn[30: 0],shiftDataIn[31   ]}; end
      2 : begin shiftResultLogical <= {shiftDataIn[29: 0], 2'b0};shiftResultArithmetic <= {                   shiftDataIn[29:0], 2'b0};shiftResultRotate <= {shiftDataIn[29: 0],shiftDataIn[31:30]}; end
      3 : begin shiftResultLogical <= {shiftDataIn[28: 0], 3'b0};shiftResultArithmetic <= {                   shiftDataIn[28:0], 3'b0};shiftResultRotate <= {shiftDataIn[28: 0],shiftDataIn[31:29]}; end
      4 : begin shiftResultLogical <= {shiftDataIn[27: 0], 4'b0};shiftResultArithmetic <= {                   shiftDataIn[27:0], 4'b0};shiftResultRotate <= {shiftDataIn[27: 0],shiftDataIn[31:28]}; end
      5 : begin shiftResultLogical <= {shiftDataIn[26: 0], 5'b0};shiftResultArithmetic <= {                   shiftDataIn[26:0], 5'b0};shiftResultRotate <= {shiftDataIn[26: 0],shiftDataIn[31:27]}; end
      6 : begin shiftResultLogical <= {shiftDataIn[25: 0], 6'b0};shiftResultArithmetic <= {                   shiftDataIn[25:0], 6'b0};shiftResultRotate <= {shiftDataIn[25: 0],shiftDataIn[31:26]}; end
      7 : begin shiftResultLogical <= {shiftDataIn[24: 0], 7'b0};shiftResultArithmetic <= {                   shiftDataIn[24:0], 7'b0};shiftResultRotate <= {shiftDataIn[24: 0],shiftDataIn[31:25]}; end
      8 : begin shiftResultLogical <= {shiftDataIn[23: 0], 8'b0};shiftResultArithmetic <= {                   shiftDataIn[23:0], 8'b0};shiftResultRotate <= {shiftDataIn[23: 0],shiftDataIn[31:24]}; end
      9 : begin shiftResultLogical <= {shiftDataIn[22: 0], 9'b0};shiftResultArithmetic <= {                   shiftDataIn[22:0], 9'b0};shiftResultRotate <= {shiftDataIn[22: 0],shiftDataIn[31:23]}; end
      10: begin shiftResultLogical <= {shiftDataIn[21: 0],10'b0};shiftResultArithmetic <= {                   shiftDataIn[21:0],10'b0};shiftResultRotate <= {shiftDataIn[21: 0],shiftDataIn[31:22]}; end
      11: begin shiftResultLogical <= {shiftDataIn[20: 0],11'b0};shiftResultArithmetic <= {                   shiftDataIn[20:0],11'b0};shiftResultRotate <= {shiftDataIn[20: 0],shiftDataIn[31:21]}; end
      12: begin shiftResultLogical <= {shiftDataIn[19: 0],12'b0};shiftResultArithmetic <= {                   shiftDataIn[19:0],12'b0};shiftResultRotate <= {shiftDataIn[19: 0],shiftDataIn[31:20]}; end
      13: begin shiftResultLogical <= {shiftDataIn[18: 0],13'b0};shiftResultArithmetic <= {                   shiftDataIn[18:0],13'b0};shiftResultRotate <= {shiftDataIn[18: 0],shiftDataIn[31:19]}; end
      14: begin shiftResultLogical <= {shiftDataIn[17: 0],14'b0};shiftResultArithmetic <= {                   shiftDataIn[17:0],14'b0};shiftResultRotate <= {shiftDataIn[17: 0],shiftDataIn[31:18]}; end
      15: begin shiftResultLogical <= {shiftDataIn[16: 0],15'b0};shiftResultArithmetic <= {                   shiftDataIn[16:0],15'b0};shiftResultRotate <= {shiftDataIn[16: 0],shiftDataIn[31:17]}; end
      16: begin shiftResultLogical <= {shiftDataIn[15: 0],16'b0};shiftResultArithmetic <= {                   shiftDataIn[15:0],16'b0};shiftResultRotate <= {shiftDataIn[15: 0],shiftDataIn[31:16]}; end
      17: begin shiftResultLogical <= {shiftDataIn[14: 0],17'b0};shiftResultArithmetic <= {                   shiftDataIn[14:0],17'b0};shiftResultRotate <= {shiftDataIn[14: 0],shiftDataIn[31:15]}; end
      18: begin shiftResultLogical <= {shiftDataIn[13: 0],18'b0};shiftResultArithmetic <= {                   shiftDataIn[13:0],18'b0};shiftResultRotate <= {shiftDataIn[13: 0],shiftDataIn[31:14]}; end
      19: begin shiftResultLogical <= {shiftDataIn[12: 0],19'b0};shiftResultArithmetic <= {                   shiftDataIn[12:0],19'b0};shiftResultRotate <= {shiftDataIn[12: 0],shiftDataIn[31:13]}; end
      20: begin shiftResultLogical <= {shiftDataIn[11: 0],20'b0};shiftResultArithmetic <= {                   shiftDataIn[11:0],20'b0};shiftResultRotate <= {shiftDataIn[11: 0],shiftDataIn[31:12]}; end
      21: begin shiftResultLogical <= {shiftDataIn[10: 0],21'b0};shiftResultArithmetic <= {                   shiftDataIn[10:0],21'b0};shiftResultRotate <= {shiftDataIn[10: 0],shiftDataIn[31:11]}; end
      22: begin shiftResultLogical <= {shiftDataIn[ 9: 0],22'b0};shiftResultArithmetic <= {                   shiftDataIn[ 9:0],22'b0};shiftResultRotate <= {shiftDataIn[ 9: 0],shiftDataIn[31:10]}; end
      23: begin shiftResultLogical <= {shiftDataIn[ 8: 0],23'b0};shiftResultArithmetic <= {                   shiftDataIn[ 8:0],23'b0};shiftResultRotate <= {shiftDataIn[ 8: 0],shiftDataIn[31: 9]}; end
      24: begin shiftResultLogical <= {shiftDataIn[ 7: 0],24'b0};shiftResultArithmetic <= {                   shiftDataIn[ 7:0],24'b0};shiftResultRotate <= {shiftDataIn[ 7: 0],shiftDataIn[31: 8]}; end
      25: begin shiftResultLogical <= {shiftDataIn[ 6: 0],25'b0};shiftResultArithmetic <= {                   shiftDataIn[ 6:0],25'b0};shiftResultRotate <= {shiftDataIn[ 6: 0],shiftDataIn[31: 7]}; end
      26: begin shiftResultLogical <= {shiftDataIn[ 5: 0],26'b0};shiftResultArithmetic <= {                   shiftDataIn[ 5:0],26'b0};shiftResultRotate <= {shiftDataIn[ 5: 0],shiftDataIn[31: 6]}; end
      27: begin shiftResultLogical <= {shiftDataIn[ 4: 0],27'b0};shiftResultArithmetic <= {                   shiftDataIn[ 4:0],27'b0};shiftResultRotate <= {shiftDataIn[ 4: 0],shiftDataIn[31: 5]}; end
      28: begin shiftResultLogical <= {shiftDataIn[ 3: 0],28'b0};shiftResultArithmetic <= {                   shiftDataIn[ 3:0],28'b0};shiftResultRotate <= {shiftDataIn[ 3: 0],shiftDataIn[31: 4]}; end
      29: begin shiftResultLogical <= {shiftDataIn[ 2: 0],29'b0};shiftResultArithmetic <= {                   shiftDataIn[ 2:0],29'b0};shiftResultRotate <= {shiftDataIn[ 2: 0],shiftDataIn[31: 3]}; end
      30: begin shiftResultLogical <= {shiftDataIn[ 1: 0],30'b0};shiftResultArithmetic <= {                   shiftDataIn[ 1:0],30'b0};shiftResultRotate <= {shiftDataIn[ 1: 0],shiftDataIn[31: 2]}; end
      31: begin shiftResultLogical <= {shiftDataIn[    0],31'b0};shiftResultArithmetic <= {                   shiftDataIn[   0],31'b0};shiftResultRotate <= {shiftDataIn[    0],shiftDataIn[31: 1]}; end
      endcase
    end else begin
      case(shiftDistance)
      0 : begin shiftResultLogical <= {      shiftDataIn[31: 0]};shiftResultArithmetic <= {                        shiftDataIn[31: 0]};shiftResultRotate <= {                   shiftDataIn[31: 0]}; end
      1 : begin shiftResultLogical <= { 1'b0,shiftDataIn[31: 1]};shiftResultArithmetic <= {{( 1){shiftDataIn[31]}},shiftDataIn[31: 1]};shiftResultRotate <= {shiftDataIn[    0],shiftDataIn[31: 1]}; end
      2 : begin shiftResultLogical <= { 2'b0,shiftDataIn[31: 2]};shiftResultArithmetic <= {{( 2){shiftDataIn[31]}},shiftDataIn[31: 2]};shiftResultRotate <= {shiftDataIn[ 1: 0],shiftDataIn[31: 2]}; end
      3 : begin shiftResultLogical <= { 3'b0,shiftDataIn[31: 3]};shiftResultArithmetic <= {{( 3){shiftDataIn[31]}},shiftDataIn[31: 3]};shiftResultRotate <= {shiftDataIn[ 2: 0],shiftDataIn[31: 3]}; end
      4 : begin shiftResultLogical <= { 4'b0,shiftDataIn[31: 4]};shiftResultArithmetic <= {{( 4){shiftDataIn[31]}},shiftDataIn[31: 4]};shiftResultRotate <= {shiftDataIn[ 3: 0],shiftDataIn[31: 4]}; end
      5 : begin shiftResultLogical <= { 5'b0,shiftDataIn[31: 5]};shiftResultArithmetic <= {{( 5){shiftDataIn[31]}},shiftDataIn[31: 5]};shiftResultRotate <= {shiftDataIn[ 4: 0],shiftDataIn[31: 5]}; end
      6 : begin shiftResultLogical <= { 6'b0,shiftDataIn[31: 6]};shiftResultArithmetic <= {{( 6){shiftDataIn[31]}},shiftDataIn[31: 6]};shiftResultRotate <= {shiftDataIn[ 5: 0],shiftDataIn[31: 6]}; end
      7 : begin shiftResultLogical <= { 7'b0,shiftDataIn[31: 7]};shiftResultArithmetic <= {{( 7){shiftDataIn[31]}},shiftDataIn[31: 7]};shiftResultRotate <= {shiftDataIn[ 6: 0],shiftDataIn[31: 7]}; end
      8 : begin shiftResultLogical <= { 8'b0,shiftDataIn[31: 8]};shiftResultArithmetic <= {{( 8){shiftDataIn[31]}},shiftDataIn[31: 8]};shiftResultRotate <= {shiftDataIn[ 7: 0],shiftDataIn[31: 8]}; end
      9 : begin shiftResultLogical <= { 9'b0,shiftDataIn[31: 9]};shiftResultArithmetic <= {{( 9){shiftDataIn[31]}},shiftDataIn[31: 9]};shiftResultRotate <= {shiftDataIn[ 8: 0],shiftDataIn[31: 9]}; end
      10: begin shiftResultLogical <= {10'b0,shiftDataIn[31:10]};shiftResultArithmetic <= {{(10){shiftDataIn[31]}},shiftDataIn[31:10]};shiftResultRotate <= {shiftDataIn[ 9: 0],shiftDataIn[31:10]}; end
      11: begin shiftResultLogical <= {11'b0,shiftDataIn[31:11]};shiftResultArithmetic <= {{(11){shiftDataIn[31]}},shiftDataIn[31:11]};shiftResultRotate <= {shiftDataIn[10: 0],shiftDataIn[31:11]}; end
      12: begin shiftResultLogical <= {12'b0,shiftDataIn[31:12]};shiftResultArithmetic <= {{(12){shiftDataIn[31]}},shiftDataIn[31:12]};shiftResultRotate <= {shiftDataIn[11: 0],shiftDataIn[31:12]}; end
      13: begin shiftResultLogical <= {13'b0,shiftDataIn[31:13]};shiftResultArithmetic <= {{(13){shiftDataIn[31]}},shiftDataIn[31:13]};shiftResultRotate <= {shiftDataIn[12: 0],shiftDataIn[31:13]}; end
      14: begin shiftResultLogical <= {14'b0,shiftDataIn[31:14]};shiftResultArithmetic <= {{(14){shiftDataIn[31]}},shiftDataIn[31:14]};shiftResultRotate <= {shiftDataIn[13: 0],shiftDataIn[31:14]}; end
      15: begin shiftResultLogical <= {15'b0,shiftDataIn[31:15]};shiftResultArithmetic <= {{(15){shiftDataIn[31]}},shiftDataIn[31:15]};shiftResultRotate <= {shiftDataIn[14: 0],shiftDataIn[31:15]}; end
      16: begin shiftResultLogical <= {16'b0,shiftDataIn[31:16]};shiftResultArithmetic <= {{(16){shiftDataIn[31]}},shiftDataIn[31:16]};shiftResultRotate <= {shiftDataIn[15: 0],shiftDataIn[31:16]}; end
      17: begin shiftResultLogical <= {17'b0,shiftDataIn[31:17]};shiftResultArithmetic <= {{(17){shiftDataIn[31]}},shiftDataIn[31:17]};shiftResultRotate <= {shiftDataIn[16: 0],shiftDataIn[31:17]}; end
      18: begin shiftResultLogical <= {18'b0,shiftDataIn[31:18]};shiftResultArithmetic <= {{(18){shiftDataIn[31]}},shiftDataIn[31:18]};shiftResultRotate <= {shiftDataIn[17: 0],shiftDataIn[31:18]}; end
      19: begin shiftResultLogical <= {19'b0,shiftDataIn[31:19]};shiftResultArithmetic <= {{(19){shiftDataIn[31]}},shiftDataIn[31:19]};shiftResultRotate <= {shiftDataIn[18: 0],shiftDataIn[31:19]}; end
      20: begin shiftResultLogical <= {20'b0,shiftDataIn[31:20]};shiftResultArithmetic <= {{(20){shiftDataIn[31]}},shiftDataIn[31:20]};shiftResultRotate <= {shiftDataIn[19: 0],shiftDataIn[31:20]}; end
      21: begin shiftResultLogical <= {21'b0,shiftDataIn[31:21]};shiftResultArithmetic <= {{(21){shiftDataIn[31]}},shiftDataIn[31:21]};shiftResultRotate <= {shiftDataIn[20: 0],shiftDataIn[31:21]}; end
      22: begin shiftResultLogical <= {22'b0,shiftDataIn[31:22]};shiftResultArithmetic <= {{(22){shiftDataIn[31]}},shiftDataIn[31:22]};shiftResultRotate <= {shiftDataIn[21: 0],shiftDataIn[31:22]}; end
      23: begin shiftResultLogical <= {23'b0,shiftDataIn[31:23]};shiftResultArithmetic <= {{(23){shiftDataIn[31]}},shiftDataIn[31:23]};shiftResultRotate <= {shiftDataIn[22: 0],shiftDataIn[31:23]}; end
      24: begin shiftResultLogical <= {24'b0,shiftDataIn[31:24]};shiftResultArithmetic <= {{(24){shiftDataIn[31]}},shiftDataIn[31:24]};shiftResultRotate <= {shiftDataIn[23: 0],shiftDataIn[31:24]}; end
      25: begin shiftResultLogical <= {25'b0,shiftDataIn[31:25]};shiftResultArithmetic <= {{(25){shiftDataIn[31]}},shiftDataIn[31:25]};shiftResultRotate <= {shiftDataIn[24: 0],shiftDataIn[31:25]}; end
      26: begin shiftResultLogical <= {26'b0,shiftDataIn[31:26]};shiftResultArithmetic <= {{(26){shiftDataIn[31]}},shiftDataIn[31:26]};shiftResultRotate <= {shiftDataIn[25: 0],shiftDataIn[31:26]}; end
      27: begin shiftResultLogical <= {27'b0,shiftDataIn[31:27]};shiftResultArithmetic <= {{(27){shiftDataIn[31]}},shiftDataIn[31:27]};shiftResultRotate <= {shiftDataIn[26: 0],shiftDataIn[31:27]}; end
      28: begin shiftResultLogical <= {28'b0,shiftDataIn[31:28]};shiftResultArithmetic <= {{(28){shiftDataIn[31]}},shiftDataIn[31:28]};shiftResultRotate <= {shiftDataIn[27: 0],shiftDataIn[31:28]}; end
      29: begin shiftResultLogical <= {29'b0,shiftDataIn[31:29]};shiftResultArithmetic <= {{(29){shiftDataIn[31]}},shiftDataIn[31:29]};shiftResultRotate <= {shiftDataIn[28: 0],shiftDataIn[31:29]}; end
      30: begin shiftResultLogical <= {30'b0,shiftDataIn[31:30]};shiftResultArithmetic <= {{(30){shiftDataIn[31]}},shiftDataIn[31:30]};shiftResultRotate <= {shiftDataIn[29: 0],shiftDataIn[31:30]}; end
      31: begin shiftResultLogical <= {31'b0,shiftDataIn[   31]};shiftResultArithmetic <= {{(31){shiftDataIn[31]}},shiftDataIn[   31]};shiftResultRotate <= {shiftDataIn[30: 0],shiftDataIn[   31]}; end
      endcase
    end
  end
`endif

  wire [31:0] mulDataB = stage2_cmd_ext ? stage2_regfileB : stage2_IMM16sx;
  wire [31:0] mulResultSigned;
`ifdef isALTERA
  lpm_mult	lpm_mult_component (
        .dataa (stage2_regfileA),
        .datab (mulDataB),
        .result (mulResultSigned),
        .aclr (1'b0),
        .clken (1'b1),
        .clock (1'b0),
        .sum (1'b0));
  defparam
    lpm_mult_component.lpm_hint = "MAXIMIZE_SPEED=1",
    lpm_mult_component.lpm_representation = "SIGNED",
    lpm_mult_component.lpm_type = "LPM_MULT",
    lpm_mult_component.lpm_widtha = 32,
    lpm_mult_component.lpm_widthb = 32,
    lpm_mult_component.lpm_widthp = 64;
`endif

`ifdef isVIVADO
  mult32 mult32_ins (
        .A (stage2_regfileA),
        .B (mulDataB),
        .P (mulResultSigned));
`endif


  //////////////////////////////////////////////////////////
  
  //4，stage2 执行
  wire       holdStage = avm_m0_waitrequest;
  //+096,+034040  ->   +096,+032931 


  //wire [31:0] dsAddr = ds + stage2_regfileA + IMM16sx;
  wire [31:0] exec_address = stage2_regfileA + stage2_IMM16sx;
  reg  [31:0] exec_writedata;
  reg   [3:0] byteenable;
  reg         exec_read;
  reg         exec_write;
  always @(*) begin
    exec_read <= 0;
    exec_write <= 0;
    byteenable <= 4'b1111;
    exec_writedata <= stage2_regfileB;
    if(stage2_Valid && stage2_MEMAccess) begin
      case(stage2_cmd)
        //ldw reg, regins              @          11 @                      0 @   7 @          000111      0x07 ldw rB, byte_offset(rA)
        3'b000 : begin//ok
          exec_read <= 1;
        end
        //stw reg, regins              @          11 @                      0 @  15 @          001111      0x0f stw rB, byte_offset(rA)
        3'b001 : begin//ok
          exec_write <= 1;
        end
        //ldbu reg, regins             @          11 @                      0 @  23 @          010111      0x17
        3'b010 : begin//ok
          exec_read <= 1;
        end
        //ldb reg, regins              @          11 @                      0 @  31 @          011111      0x1f*
        3'b011 : begin//ok
          exec_read <= 1;
        end
        //ldhu reg, regins             @          11 @                      0 @  39 @          100111      0x27
        3'b100 : begin//ok
          exec_read <= 1;
        end
        //ldh reg, regins              @          11 @                      0 @  47 @          101111      0x2f
        3'b101 : begin//ok
          exec_read <= 1;
        end
        //stb reg, regins              @          11 @                      0 @  55 @          110111      0x37*
        3'b110 : begin//ok
          case(exec_address[1:0])
            0:begin byteenable <= 4'b0001; exec_writedata <= {24'b0,stage2_regfileB[7:0]};end
            1:begin byteenable <= 4'b0010; exec_writedata <= {16'b0,stage2_regfileB[7:0],8'b0};end
            2:begin byteenable <= 4'b0100; exec_writedata <= {8'b0,stage2_regfileB[7:0],16'b0};end
            3:begin byteenable <= 4'b1000; exec_writedata <= {stage2_regfileB[7:0],24'b0};end
          endcase
          exec_write <= 1;
        end
        //sth reg, regins              @          11 @                      0 @  63 @          111111      0x3f*
        3'b111 : begin//ok
          case(exec_address[1])
            0:begin byteenable <= 4'b0011; exec_writedata <= {16'b0,stage2_regfileB[15:0]};end
            1:begin byteenable <= 4'b1100; exec_writedata <= {stage2_regfileB[15:0],16'b0};end
          endcase
          exec_write <= 1;
        end
      endcase
    end
  end

  always @(*) begin
    if(stage2_cmd_ext == 0)begin
      case(stage2_cmd)
      //#pc ext                                                                00011
      3'b000 : begin//ok
        pcResult <= nextpc;
      end
      //call sym                     @          22 @                      2 @  000111
      3'b001 : begin//ok
        //pcResult <= {pc[31:28],stage2_IMM26,2'b00};
        pcResult <= nextpc;//dummy
      end
      //bge reg, reg, sym            @          15 @                      0 @  001111
      3'b010 : begin//ok
        if(stage2_res_cmpge) begin//if ((signed) rA >= (signed) rB)
          pcResult <= nextpc + stage2_IMM16sx;//then PC ← PC + 4 + σ(IMM16)
        end else begin
          pcResult <= nextpc;//else PC ← PC + 4
        end
      end
      //blt reg, reg, sym            @          15 @                      0 @  010111
      3'b011 : begin//ok
        if(stage2_res_cmplt) begin//if ((signed) rA < (signed) rB)
          pcResult <= nextpc + stage2_IMM16sx;//then PC ← PC + 4 + σ(IMM16)
        end else begin
          pcResult <= nextpc;//else PC ← PC + 4
        end
      end
      //bne reg, reg, sym            @          15 @                      0 @  011111
      3'b100 : begin//ok
        if(stage2_res_cmpne) begin
          pcResult <= nextpc + stage2_IMM16sx;
        end else begin
          pcResult <= nextpc;
        end
      end
      //beq reg, reg, sym            @          15 @                      0 @  100111
      3'b101 : begin//ok
        if(stage2_res_cmpeq) begin
          pcResult <= nextpc + stage2_IMM16sx;
        end else begin
          pcResult <= nextpc;
        end
      end
      //bgeu reg, reg, sym           @          15 @                      0 @  101111
      3'b110 : begin//ok
        if(!stage2_res_cmpltu) begin//if ((unsigned) rA >= (unsigned) rB) 
          pcResult <= nextpc + stage2_IMM16sx;//then PC ← PC + 4 + σ(IMM16)
        end else begin
          pcResult <= nextpc;//else PC ← PC + 4
        end
      end
      //bltu reg, reg, sym           @          15 @                      0 @  110111
      3'b111 : begin//ok
        if(stage2_res_cmpltu) begin//if ((unsigned) rA < (unsigned) rB) 
          pcResult <= nextpc + stage2_IMM16sx;//then PC ← PC + 4 + σ(IMM16)
        end else begin
          pcResult <= nextpc;//else PC ← PC + 4
        end
      end
      endcase
    end else begin
      case(stage2_cmd)
      //callr reg                    @          50 @                      1 @  111111
      3'b000 : begin//ok
        pcResult <= stage2_regfileA;
      end
      //jmp reg                      @          51 @                      1 @  111111
      //ret                          @          55 @                      1 @  111111         TODO 等效于 jmp reg 可以合并 腾出指令空间
      3'b001 : begin//ok
        pcResult <= stage2_regfileA;
      end
      //reti                         @          56 @                      1 @  111111
      3'b010 : begin//ok
        pcResult <= stage2_regfileA;
      end
      //#irqcall                     @          57 @                      1 @  111111
      //r29 ea Exception return address
      3'b011 : begin//ok
        //stage1_regA <= 0; stage1_IMM16sx <= {irq_id,2'b0};
        //wire [31:0] exec_address = stage2_regfileA + stage2_IMM16sx;
        pcResult <= stage2_regfileA;//irq_addr;
      end
      //hlt ins                      @          54 @                      1 @  111111
      3'b100 : begin//ok
        pcResult <= nextpc;
      end
      //sti reg, reg
      3'b101 : begin
        pcResult <= nextpc;
      end
      //setirq reg, ins
      3'b110 : begin//ok
        pcResult <= nextpc;
      end
      //stoff reg,ins                @          53 @                      1 @  111111
      3'b111 : begin//ok
        pcResult <= nextpc;
      end
      endcase
    end
  end
  
  reg        write_debug_stash;
  reg [31:0] write_debug_stash_data;
  always @(posedge clk or negedge cpu_reset_n) begin
    if (!cpu_reset_n) begin
      //stage3寄存器初始化
      stage3_Valid <= 0;
      stage3_regChange <= 0;
      stage3_irq <= 0;
      stage3_regResult_PCChange <= 0;
      stage3_regResult_MEMAccess <= 0;
      stage3_regResult_CMP <= 0;
      stage3_regResult_ALU <= 0;
      stage3_regResult_SHIFT <= 0;
      irq_enable <= 0;
      //halt_cpu <= 0;
      write_debug_stash <= 0;
      write_debug_stash_data <= 0;
    end else begin
      stage3_Valid <= 0;
      write_debug_stash <= 0;
      stage3_irq <= 0;
      if(stage2_Valid)begin
        stage3_Valid <= 1;

        stage3_regResult_PCChange <= 0;
        stage3_regResult_MEMAccess <= 0;
        stage3_regResult_CMP <= 0;
        stage3_regResult_ALU <= 0;
        stage3_regResult_SHIFT <= 0;

        if(stage2_PCChange)begin
          stage3_regChange <= 0;
          if(stage2_cmd_ext == 0)begin
            case(stage2_cmd)
            //call sym                     @          22 @                      2 @  000111
            3'b001 : begin//ok
              //pcResult <= {pc[31:28],stage2_IMM26,2'b00};
              //regfile[31] <= nextpc; code is 31
              stage3_regResult_PCChange <= stage2_nextpc;
              //regResultRA <= 1;
              stage3_regChange <= 31;
            end
            endcase
          end else begin
            case(stage2_cmd)
            //callr reg                    @          50 @                      1 @  111111
            3'b000 : begin//ok
              //pcResult <= stage2_regfileA;
              stage3_regResult_PCChange <= nextpc;//rC ← rA + rB
              stage3_regChange <= stage2_regC;//regResultC <= 1;// c is ra
            end
            //jmp reg                      @          51 @                      1 @  111111
            //ret                          @          55 @                      1 @  111111         TODO 等效于 jmp reg 可以合并 腾出指令空间
            3'b001 : begin//ok
              //pcResult <= stage2_regfileA;
            end
            //reti                         @          56 @                      1 @  111111
            3'b010 : begin//ok
              //pcResult <= stage2_regfileA;
              irq_enable <= 1;
            end
            //#irqcall                     @          57 @                      1 @  111111
            //r29 ea Exception return address
            3'b011 : begin//ok
            
              //stage1_regA <= 0; stage1_IMM16sx <= {irq_id,2'b0};
              //wire [31:0] exec_address = stage2_regfileA + stage2_IMM16sx;
              //pcResult <= stage2_regfileA;//irq_addr;
              irq_enable <= 0;
              stage3_regResult_PCChange <= pc;
              stage3_regChange <= stage2_regC;//r29 ea Exception return address
            end
            //hlt ins                      @          54 @                      1 @  111111
            3'b100 : begin//ok
              //halt_cpu <= stage2_IMM6[0];
              //pcResult <= nextpc;
            end
            //sti reg, reg
            3'b101 : begin
              irq_enable <= stage2_regfileB[0];
              //pcResult <= nextpc;
              stage3_regResult_PCChange <= {31'b0,irq_enable};//rC ← rA + rB
              stage3_regChange <= stage2_regC;//regResultC <= 1;// c is ra
            end
            //setirq reg, ins
            3'b110 : begin//ok
              stage3_irq <= 1;
              //pcResult <= nextpc;
              stage3_regResult_PCChange <= stage2_regfileB;
              stage3_regChange <= stage2_regfileA[4:0];
            end
            //stoff reg,ins                @          53 @                      1 @  111111
            3'b111 : begin//ok
              if(stage2_IMM6[0])begin
                private_offset <= {stage2_regfileA[31:2],2'b0};
              end else begin
                private_offset_rear <= {stage2_regfileA[31:2],2'b0};
              end
              //pcResult <= nextpc;
            end
            endcase
          end
        end else begin
          stage3_regChange <= stage2_regChange;
        end
        
        if(stage2_MEMAccess)begin
          case(stage2_cmd)
            //ldw reg, regins              @          11 @                      0 @   7 @          000111      0x07 ldw rB, byte_offset(rA)
            3'b000 : begin//ok
              stage3_regResult_MEMAccess <= avm_m0_readdata;
            end
            //stw reg, regins              @          11 @                      0 @  15 @          001111      0x0f stw rB, byte_offset(rA)
            3'b001 : begin//ok
              //dummy
              stage3_regResult_MEMAccess <= avm_m0_readdata;
            end
            //ldbu reg, regins             @          11 @                      0 @  23 @          010111      0x17
            3'b010 : begin//ok
              case(exec_address[1:0])
                0:begin stage3_regResult_MEMAccess <= {24'b0,avm_m0_readdata[ 7: 0]};end
                1:begin stage3_regResult_MEMAccess <= {24'b0,avm_m0_readdata[15: 8]};end
                2:begin stage3_regResult_MEMAccess <= {24'b0,avm_m0_readdata[23:16]};end
                3:begin stage3_regResult_MEMAccess <= {24'b0,avm_m0_readdata[31:24]};end
              endcase
            end
            //ldb reg, regins              @          11 @                      0 @  31 @          011111      0x1f*
            3'b011 : begin//ok
              case(exec_address[1:0])
                0:begin stage3_regResult_MEMAccess <= {{24{avm_m0_readdata[ 7]}},avm_m0_readdata[ 7: 0]};end
                1:begin stage3_regResult_MEMAccess <= {{24{avm_m0_readdata[15]}},avm_m0_readdata[15: 8]};end
                2:begin stage3_regResult_MEMAccess <= {{24{avm_m0_readdata[23]}},avm_m0_readdata[23:16]};end
                3:begin stage3_regResult_MEMAccess <= {{24{avm_m0_readdata[31]}},avm_m0_readdata[31:24]};end
              endcase
            end
            //ldhu reg, regins             @          11 @                      0 @  39 @          100111      0x27
            3'b100 : begin//ok
              case(exec_address[1])
                0:begin stage3_regResult_MEMAccess <= {16'b0,avm_m0_readdata[15: 0]};end
                1:begin stage3_regResult_MEMAccess <= {16'b0,avm_m0_readdata[31:16]};end
              endcase
            end
            //ldh reg, regins              @          11 @                      0 @  47 @          101111      0x2f
            3'b101 : begin//ok
              case(exec_address[1])
                0:begin stage3_regResult_MEMAccess <= {{16{avm_m0_readdata[15]}},avm_m0_readdata[15: 0]};end
                1:begin stage3_regResult_MEMAccess <= {{16{avm_m0_readdata[31]}},avm_m0_readdata[31:16]};end
              endcase
            end
            //stb reg, regins              @          11 @                      0 @  55 @          110111      0x37*
            3'b110 : begin//ok
              //dummy
              case(exec_address[1])
                0:begin stage3_regResult_MEMAccess <= {16'b0,avm_m0_readdata[15: 0]};end
                1:begin stage3_regResult_MEMAccess <= {16'b0,avm_m0_readdata[31:16]};end
              endcase
            end
            //sth reg, regins              @          11 @                      0 @  63 @          111111      0x3f*
            3'b111 : begin//ok
              //dummy
              case(exec_address[1])
                0:begin stage3_regResult_MEMAccess <= {{16{avm_m0_readdata[15]}},avm_m0_readdata[15: 0]};end
                1:begin stage3_regResult_MEMAccess <= {{16{avm_m0_readdata[31]}},avm_m0_readdata[31:16]};end
              endcase
            end
          endcase
        end

        if(stage2_CMP)begin
          case(stage2_cmd)
            //cmpgei reg, reg, ins         @          10 @                      0 @  001000
            //cmpge reg, reg, reg          @          30 @                      3 @  001100
            3'b001 : begin stage3_regResult_CMP[0] <= stage2_cmd_ext ? stage2_res_cmpge : stage2_res_cmpgei;end//{31'b0,($signed(stage2_regfileA) >= $signed(stage2_IMM16sx))}; end//if ((signed) rA >= (signed) σ(IMM16)) then rB ← 1 else rB ← 0
            //cmplti reg, reg, ins         @          10 @                      0 @  010000
            //cmplt reg, reg, reg          @          30 @                      3 @  010100
            3'b010 : begin stage3_regResult_CMP[0] <= stage2_cmd_ext ? stage2_res_cmplt : stage2_res_cmplti;end//{31'b0,($signed(stage2_regfileA) < $signed(stage2_IMM16sx))}; end//if ((signed) rA < (signed) σ(IMM16))
            //cmpnei reg, reg, ins         @          10 @                      0 @  011000
            //cmpne reg, reg, reg          @          30 @                      3 @  011100
            3'b011 : begin stage3_regResult_CMP[0] <= stage2_cmd_ext ? stage2_res_cmpne : stage2_res_cmpnei;end//{31'b0,(stage2_regfileA != stage2_IMM16sx)}; end//if (rA != σ(IMM16)) then rB ← 1 else rB ← 0
            //cmpeqi reg, reg, ins         @          10 @                      0 @  100000
            //cmpeq reg, reg, reg          @          30 @                      3 @  100100
            3'b100 : begin stage3_regResult_CMP[0] <= stage2_cmd_ext ? stage2_res_cmpeq : stage2_res_cmpeqi;end//{31'b0,(stage2_regfileA == stage2_IMM16sx)}; end//if (rA == σ(IMM16)) then rB ← 1 else rB ← 0
            //cmpgeui reg, reg, ins        @          10 @                      0 @  101000
            //#cmpgeu reg, reg, reg        @          30 @                      3 @  101100
            3'b101 : begin stage3_regResult_CMP[0] <= stage2_cmd_ext ? stage2_res_cmpgeu : stage2_res_cmpgeui;end//{31'b0,(stage2_regfileA >= stage2_IMM16zx)}; end//if ((unsigned) rA >= (unsigned) (0x0000 : IMM16)) then rB ← 1 else rB ← 0
            //cmpltui reg, reg, ins        @          10 @                      0 @  110000
            //cmpltu reg, reg, reg         @          30 @                      3 @  110100
            3'b110 : begin stage3_regResult_CMP[0] <= stage2_cmd_ext ? stage2_res_cmpltu : stage2_res_cmpltui;end//{31'b0,(stage2_regfileA < stage2_IMM16zx)}; end//if ((unsigned) rA < (unsigned) (0x0000 : IMM16)) then rB ← 1 else rB ← 0
            // stashi
            // stash
            3'b111 : begin write_debug_stash <= 1; write_debug_stash_data <= stage2_cmd_ext ? stage2_regfileA : stage2_IMM16sx; end

            default : begin stage3_regResult_CMP[0] <= 0;end
          endcase
        end

            //#01 alu
            //
            //#01 alu ext

        if(stage2_ALU)begin
          case(stage2_cmd)
            //addi reg, reg, ins           @          10 @                      0 @  00001
            //add reg, reg, reg            @          30 @                      1 @  00001
            3'b000 : begin stage3_regResult_ALU <= stage2_res_add;end//stage2_regfileA + stage2_IMM16sx; end//rB ← rA + σ(IMM16)
            //andi reg, reg, ins           @          10 @                      0 @  00101
            //and reg, reg, reg            @          30 @                      1 @  00101
            3'b001 : begin stage3_regResult_ALU <= stage2_res_and;end//stage2_regfileA & stage2_regfileB; end// rC ← rA | rB
            //ori  reg, reg, ins           @          10 @                      0 @  01001
            //or reg, reg, reg             @          30 @                      1 @  01001
            3'b010 : begin stage3_regResult_ALU <= stage2_res_or;end//stage2_regfileA | stage2_regfileB; end// rC ← rA | rB
            //xori reg, reg, ins           @          10 @                      0 @  01101
            //xor reg, reg, reg            @          30 @                      1 @  01101
            3'b011 : begin stage3_regResult_ALU <= stage2_res_xor;end//{stage2_regfileA[31:16], (stage2_regfileA[15:0] ^ stage2_IMM16)}; end//rB ← rA ^ (0x0000 : IMM16)
            //muli reg, reg, ins           @          10 @                      0 @  10001
            //mul reg, reg, reg            @          30 @                      1 @  10001
            3'b100 : begin stage3_regResult_ALU <= mulResultSigned;end
            //andhi reg, reg, ins          @          10 @                      0 @  10101
            //sub reg, reg, reg            @          30 @                      1 @  10101
            3'b101 : begin stage3_regResult_ALU <= stage2_res_sub_andhi;end//stage2_cmd_ext ? stage2_res_sub : stage2_res_andhi;end//{(stage2_regfileA[31:16] & stage2_IMM16), 16'b0}; end//rB ← rA & (IMM16 : 0x0000)
            //orhi reg, reg, ins           @          10 @                      0 @  11001
            //nor reg, reg, reg            @          30 @                      1 @  11001
            3'b110 : begin stage3_regResult_ALU <= stage2_res_nor_orhi;end// stage2_cmd_ext ? stage2_res_nor : stage2_res_orhi;end//~(stage2_regfileA | stage2_regfileB); end// rC ← ~(rA | rB)
            //xorhi reg, reg, ins          @          10 @                      0 @  11101
            3'b111 : begin stage3_regResult_ALU <= stage2_res_xorhi;end//{(stage2_regfileA[31:16] ^ stage2_IMM16), stage2_regfileA[15:0]}; end//rB ← rA ^ (IMM16 : 0x0000)
          endcase
        end

        if(stage2_SHIFT1 || stage2_SHIFT2)begin
          case(stage2_cmd)
            //slli reg, reg, ins            @         31 @                      1 @  00010
            //sll reg, reg, reg            @          30 @                      1 @  00011
            3'b000 : begin stage3_regResult_SHIFT <= shiftResultLogical; end
            //srai reg, reg, ins            @         31 @                      1 @  00110
            //sra reg, reg, reg            @          30 @                      1 @  00111
            3'b001 : begin stage3_regResult_SHIFT <= shiftResultArithmetic; end
            //srli reg, reg, ins            @         31 @                      1 @  01010
            //srl reg, reg, reg            @          30 @                      1 @  01011
            3'b010 : begin stage3_regResult_SHIFT <= shiftResultLogical; end
            //roli reg, reg, ins            @         31 @                      1 @  01110
            //rol reg, reg, reg            @          30 @                      1 @  01111
            3'b011 : begin stage3_regResult_SHIFT <= shiftResultRotate; end

            3'b110 : begin stage3_regResult_SHIFT <= stage2_regfileB_byteclip; end
            3'b111 : begin
              case(stage2_IMM6[1:0])
                0:stage3_regResult_SHIFT <= stage2_setRGB_r;
                1:stage3_regResult_SHIFT <= stage2_setRGB_g;
                2:stage3_regResult_SHIFT <= stage2_setRGB_b;
                3:stage3_regResult_SHIFT <= stage2_setRGB_rgb;
              endcase
            end//setrgb
          endcase
        end
        //if(stage2_parity_check_error)begin
        //  halt_cpu <= 1;
        //end
      end
    end
  end
  reg         stage3_Valid;
  reg         stage3_irq;
  reg  [4:0]  stage3_regChange;
  reg  [31:0] stage3_regResult_PCChange;
  reg  [31:0] stage3_regResult_MEMAccess;
  reg  [31:0] stage3_regResult_CMP;
  reg  [31:0] stage3_regResult_ALU;
  reg  [31:0] stage3_regResult_SHIFT;
  wire [31:0] stage3_regResult = stage3_regResult_PCChange | 
                                 stage3_regResult_MEMAccess | 
                                 stage3_regResult_CMP | 
                                 stage3_regResult_ALU | 
                                 stage3_regResult_SHIFT;
  //////////////////////////////////////////////////////////

  //读A，debug
  
  //读端口 分2个周期读
  //周期0 从总线上获取到源寄存器ID
  //周期1 从寄存器获取到源1的值  从寄存器获取到源2的值
  //周期2 获取到计算结果
  //周期3 写入结果
  //写用一个端口
  reg  [31:0] regfile[64];
  wire [31:0] reg_outA = regfile[{stage1_irq, stage1_regA}];
  wire [31:0] reg_outB = regfile[{1'b0, stage1_regB}];

  assign debug_regData = reg_outA;
  
  //5，stage3 寄存器/PC 更新
  always @(posedge clk or negedge cpu_reset_n) begin
    if (!cpu_reset_n) begin
    end else begin
      if(stage3_Valid)begin
        if({stage3_irq, stage3_regChange} != 0)begin
          regfile[{stage3_irq, stage3_regChange}] <= stage3_regResult;
        end
      end
    end
  end

endmodule



